package org.fixies.utils;

import java.util.Collection;

/**
 * 精査クラス
 *
 * @author Kawasaki
 */
public final class Validator {

    /**
     * コンストラクタ<br/>
     * 本クラスはインスタンス化できない。
     */
    private Validator() {
    }


    /**
     * 引数で与えられた参照がnullでないことを表明する。
     *
     * @param message 精査失敗時のメッセージ
     * @param obj     精査対象の参照
     */
    public static void notNull(String message, Object... obj) {
        checkNotNull(message, obj);
        for (Object e : obj) {
            checkNotNull(message, e);
        }
    }

    private static void checkNotNull(String message, Object obj) {
        if (obj == null) {
            throw new IllegalArgumentException(message);
        }

    }

    /**
     * 引数で与えられた参照がnullでないことを表明する。
     *
     * @param obj 精査対象の参照
     */
    public static void notNull(Object... obj) {
        notNull("Argument must not be null.", obj);
    }

    /**
     * 引数で与えられた文字列が空文字でないことを表明する。
     *
     * @param str 精査対象の文字列
     */
    public static void notEmpty(String str) {
        notEmpty(str, "Argument must not be empty.");
    }

    /**
     * 引数で与えられた文字列が空文字でないことを表明する。
     *
     * @param str     精査対象の文字列
     * @param message 精査失敗時のメッセージ
     */
    public static void notEmpty(String str, String message) {
        if (str == null) return;
        if (str.length() == 0) {
            throw new IllegalArgumentException(message);
        }
    }

    /**
     * 引数で与えられた文字列がnullまたは空文字列（長さ0の文字列）でない事を 表明する。
     *
     * @param str     精査対象文字列
     * @param message 精査失敗時のメッセージ
     */
    public static void notNullOrEmpty(String str, String message) {
        notNull(message, str);
        notEmpty(str, message);
    }

    /**
     * 引数で与えられた文字列がnullまたは空文字列（長さ0の文字列）でない事を 表明する。
     *
     * @param str 精査対象文字列
     */
    public static void notNullOrEmpty(String str) {
        notNullOrEmpty(str, "argument must not null or empty");
    }


    /**
     * 引数で与えられた配列がnullまたは空（長さ0の配列）でない事を表明する。
     *
     * @param objects 精査対象配列
     * @param msg     精査失敗時のメッセージ
     */
    public static void notNullOrEmpty(String msg, Object[] objects) {
        if (isNullOrEmpty(objects)) {
            throw new IllegalArgumentException(msg);
        }
    }

    /**
     * 引数で与えられた配列がnullまたは空（長さ0の配列）でない事を 表明する。
     *
     * @param objects 精査対象配列
     */
    public static void notNullOrEmpty(Object[] objects) {
        notNullOrEmpty("argument must not be null or empty.", objects);
    }

    /**
     * 引数で与えられたコレクションがnullまたは空（要素数０）でない事を 表明する。
     *
     * @param c 精査対象コレクション
     */
    public static void notNullOrEmpty(Collection<?> c) {
        notNull(c);
        notEmpty(c);
    }

    private static void notEmpty(Collection<?> c) {
        if (c.isEmpty()) {
            throw new IllegalArgumentException("argument must not be null or empty.");
        }
    }

    /**
     * 引数で与えられた文字列がnullまたは空文字列（長さ0の文字列） であるかどうか判定する
     *
     * @param str 判定対象文字列
     * @return 判定結果
     */
    public static boolean isNullOrEmpty(String str) {
        return str == null || str.length() == 0;
    }

    /**
     * 引数で与えられた配列がnullまたは空の配列（要素数0の配列）であるかどうか判定する
     *
     * @param objects 判定対象の配列
     * @return 判定結果
     */
    public static boolean isNullOrEmpty(Object[] objects) {
        if (objects == null) return true;
        for (Object e : objects) {
            if (e != null) {
                return false;
            }
        }
        return true;
    }

    /**
     * 引数で与えられた文字列がnullまたは空文字列（長さ0の文字列） であるかどうか判定する
     *
     * @param strings 判定対象文字列
     * @return 判定結果
     */
    public static boolean isNullOrEmpty(String[] strings) {
        if (strings == null) return true;
        for (String s : strings) {
            if (!isNullOrEmpty(s)) {
                return false;
            }
        }
        return true;
    }

}
